package com.koron.css2.newProjectCenter.impl;

import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.koron.css2.ServerInterface;
import com.koron.css2.baseConfig.impl.GenerateNumber;
import com.koron.css2.baseConfig.impl.GenerateNumberImpl;
import com.koron.css2.baseConfig.mapper.BaseReceiptAccessoryMapper;
import com.koron.css2.baseConfig.mapper.BusinessAreaMapper;
import com.koron.css2.clientCenter.Enum.UserInfoTempBusinessIdentification;
import com.koron.css2.clientCenter.bean.AccountInfoBean;
import com.koron.css2.clientCenter.bean.CtmInfoBean;
import com.koron.css2.clientCenter.bean.SendTemMsgAccBean;
import com.koron.css2.clientCenter.bean.UserBean;
import com.koron.css2.clientCenter.impl.OpenUserAdd;
import com.koron.css2.clientCenter.mapper.AccountInfoMapper;
import com.koron.css2.clientCenter.mapper.CtmInfoMapper;
import com.koron.css2.clientCenter.mapper.UserInfoMapper;
import com.koron.css2.meterService.dto.MsInfoDto;
import com.koron.css2.newProjectCenter.Enum.PjInfoProcessStateEnum;
import com.koron.css2.newProjectCenter.bean.*;
import com.koron.css2.newProjectCenter.bean.query.PjSettlementQuery;
import com.koron.css2.newProjectCenter.exception.UserNoException;
// import com.koron.css2.newProjectCenter.function.oracleMapper.OracleMapper;
import com.koron.css2.newProjectCenter.impl.pubUpTime.WorkDayUtils;
import com.koron.css2.newProjectCenter.mapper.*;
import com.koron.css2.newProjectCenter.service.PjInfoService;
import com.koron.css2.serviceManage.bean.*;
import com.koron.css2.serviceManage.mapper.*;
import com.koron.css2.serviceManage.utils.JsonUtils;
import com.koron.css2.serviceManage.vo.UserDiscountVO;
import com.koron.css2.serviceManage.vo.UserMixtureVO;
import com.koron.css2.systemManage.bean.OrgUserBean;
import com.koron.css2.systemManage.mapper.OrgUserMapper;
import com.koron.util.Constant;
import com.koron.util.DBSourceUtils;
import com.koron.util.SpringBeanUtil;
import com.koron.util.Tools;
import com.koron.util.secret.SecretReqUtil;
import com.koron.util.secret.StaticInfo;
import org.apache.commons.lang3.StringUtils;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.swan.bean.MessageBean;

import java.util.*;

/**
 * 工程管理-工程审批-保存
 * 20220214:因为要使用文件上传系统的附件功能，所以要在登记节点就使用前端生成的id用来关联这条数据与附件的关系
 * 1.登记节点，第一次调用PjSave接口时，前端必传：id，insertFlag=1,updateCtmFlag="1",updateAccountFlag="1"
 * 2.登记节点，不是第一次调用PjSave接口时，前端必传：id，updateCtmFlag="1",updateAccountFlag="1"
 * 3.其他节点，调用PjSave接口时,前端必传：id，updateCtmFlag="1",updateAccountFlag="1"
 * 其他还有一些必填字段，都在代码里面
 */
@Controller
public class PjSave implements ServerInterface {

    public static Logger logger = LoggerFactory.getLogger(ServerInterface.class);

    public static final String USER_NO_RULE_CODE = "USER_INFO";
    private static final String[] METER_NOT_NULL = {"build", "installBuild", "registerAccount"};
    private static final String[] PJ_TYPE_NAME = {"水表扩缩", "水表迁移"};
    private static final String PROCESS_STATUS = "报装登记";

    /**
     * INFO_APPROVAL_USER_NOS  用于资料审核后生成用户号
     */
    private static final String INFO_APPROVAL_USER_NOS = "INFO_APPROVAL_USER_NOS";
    private static final int USER_NO_SIZE = 14;

    // OracleMapper oracleMapper = SpringBeanUtil.getBean(OracleMapper.class);

    @Override
    public MessageBean<?> exec(SessionFactory factory, UserInfoBean userInfo, RequestBean req) {
        @SuppressWarnings("rawtypes")
        MessageBean<Map> msg = MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "保存成功", Map.class);
        try {
            // 1. 将入参转换为Bean对象
            String data = JsonUtils.objectToJson(req.getData()); // 将请求数据转换为JSON字符串
            JsonNode jsonNode = JsonUtils.stringToJsonNode(data); // 将JSON字符串转换为JsonNode对象
            PjInfoBean pjInfoBean = JSONObject.parseObject(jsonNode.get("consult").toString(), PjInfoBean.class); // 从JsonNode中提取"consult"部分并转换为PjInfoBean对象
            // PjInfoBean pjInfoBean = JsonUtils.objectToPojo(jsonNode.get("consult"), PjInfoBean.class); // 从JsonNode中提取"consult"部分并转换为PjInfoBean对象
            CtmInfoBean ctmInfoBean = JsonUtils.objectToPojo(jsonNode.get("ctmInfo"), CtmInfoBean.class); // 从JsonNode中提取"ctmInfo"部分并转换为CtmInfoBean对象
            AccountInfoBean accountInfoBean = JsonUtils.objectToPojo(jsonNode.get("accountInfo"), AccountInfoBean.class); // 从JsonNode中提取"accountInfo"部分并转换为AccountInfoBean对象
            List<PjMeter> pjMeterList = JsonUtils.objectToPojo(jsonNode.get("pjMeterList"), List.class); // 从JsonNode中提取"pjMeterList"部分并转换为PjMeter列表

            // 20220424: 水表迁移、水表扩容、管线改迁 不需要验证水表是否为空
            String pjType = pjInfoBean.getPjType(); // 获取项目类型
            String processState = pjInfoBean.getProcessState(); // 获取处理状态

            // 是否具有营商环境不可为空
            if (pjInfoBean.getBusinessEnvironment() == null) {
                msg.setCode(Constant.MESSAGE_INT_FAIL);
                msg.setDescription("请选择营商环境");
                return msg; // 如果营商环境为空，返回错误信息
            }

            // 登记编号不能为空
            if (StringUtils.isBlank(ctmInfoBean.getRegistrationSn())) {
                msg.setCode(Constant.MESSAGE_INT_FAIL);
                msg.setDescription("请填写登记编号");
                return msg; // 如果登记编号为空，返回错误信息
            }

            // 水表明细不能为空（特定情况下）
            if (Arrays.asList(METER_NOT_NULL).contains(processState) && StringUtils.containsAny(pjType, "1", "2", "3", "4") &&
                    pjMeterList != null && pjMeterList.isEmpty()) {
                msg.setCode(Constant.MESSAGE_INT_FAIL);
                msg.setDescription("请填写水表信息");
                return msg; // 如果水表列表为空且在特定状态下，返回错误信息
            }

            String checkResult = null;
            PubAdminAreaMapper pmapper = factory.getMapper(PubAdminAreaMapper.class, "_default"); // 获取公共行政区域映射器

            // processState为空时，置为登记
            if (StringUtils.isBlank(processState)) {
                processState = PjInfoService.REGISTER;
            }

            // 2. 如果是登记节点
            if (processState.equals(PjInfoService.REGISTER)) {
                Integer insertFlag = pjInfoBean.getInsertFlag(); // 获取插入标志

                // 2.1 如果是第一次保存（有id，但是是新增）
                if (insertFlag != null && insertFlag.equals(1)) {
                    // 2.1.1 如果不是暂存，则对部分字段进行校验
                    if (!"1".equals(jsonNode.get("temporaryFlag").asText())) {
                        checkResult = checkNode(pjInfoBean, ctmInfoBean, accountInfoBean, "register", factory); // 校验节点信息
                        if (!"OK".equals(checkResult)) {
                            return MessageBean.create(Constant.NOT_NULL, checkResult, null); // 如果校验失败，返回错误信息
                        }
                    }

                    // 发送短信
                    if ("1".equals(ctmInfoBean.getAcceptSMS())) {
                        Integer flag = sendSMS(factory, userInfo, ctmInfoBean); // 发送短信
                        if (!flag.equals(0)) {
                            return MessageBean.create(Constant.MESSAGE_INT_FAIL, "发送失败", void.class); // 如果发送失败，返回错误信息
                        }
                    }

                    // 2.1.2 设置客户地址
                    String clientAddr = pmapper.selectFullNameById(ctmInfoBean.getClientAddr()); // 查询客户地址全名
                    if (StringUtils.isEmpty(clientAddr)) {
                        ctmInfoBean.setClientAddr(null); // 如果客户地址为空，设置为null
                    }
                    if (StringUtils.isNotEmpty(pjInfoBean.getInstallAddr())) {
                        // 客户地址结构化拼接
                        ctmInfoBean.setCtmAddr(pjInfoBean.getInstallAddr());
                    }

                    // 2.1.3 保存客户信息
                    saveCtm(factory, userInfo, ctmInfoBean);

                    // 2.1.4 保存账户信息
                    saveAccount(factory, userInfo, accountInfoBean, ctmInfoBean.getCtmNo());

                    // 初始化PjInfoBean的相关字段
                    pjInfoBean.setId(Tools.getObjectId()); // 生成唯一ID
                    pjInfoBean.setUserCtmTempId(ctmInfoBean.getId()); // 设置临时客户ID
                    pjInfoBean.setUserAccountTempId(accountInfoBean.getId()); // 设置临时账户ID
                    // if (StringUtils.isBlank(pjInfoBean.getProcessState()))
                    //     pjInfoBean.setProcessState(PjInfoService.REGISTER);
                    pjInfoBean.setBillNo(Tools.getBillNo(factory, "PJ_INFO_NEW")); // 生成统一编号
                    pjInfoBean.setBillDate(new Date()); // 设置单据日期
                    pjInfoBean.setTenantId(userInfo.getCurWaterCode()); // 设置租户ID
                    pjInfoBean.setCreateName(userInfo.getUserInfo().getName()); // 设置创建人姓名
                    pjInfoBean.setCreateAccount(userInfo.getUserInfo().getAcount()); // 设置创建人账号
                    pjInfoBean.setSettlementFlag(0); // 设置结算标志

                    // 添加登记信息到数据库
                    factory.getMapper(PjInfoMapper.class).addRegister(pjInfoBean);

                    // 返回主键ID给前端用于刷新单据信息
                    String consultId = pjInfoBean.getId();
                    Map<String, String> map = new HashMap<>();
                    map.put("id", consultId);
                    msg.setData(map);

                    // 更新附件关联的单据ID
                    BaseReceiptAccessoryMapper mapper = factory.getMapper(BaseReceiptAccessoryMapper.class);
                    if (!StringUtils.isBlank(pjInfoBean.getTempId())) {
                        mapper.updateAccessoryReceiptId(consultId, pjInfoBean.getTempId());
                    }
                }
                // 2.2 如果是第二次保存（基于原数据更新）
                else {
                    MessageBean<?> NOT_NULL = saveAll(factory, userInfo, jsonNode, pjInfoBean, ctmInfoBean, accountInfoBean, pjMeterList, pmapper);
                    if (NOT_NULL != null)
                        return NOT_NULL; // 如果保存失败，返回错误信息
                }

                /*保存自定义实例时间*/
                if (!"1".equals(jsonNode.get("temporaryFlag").asText()))
                    WorkDayUtils.save(factory, userInfo, pjInfoBean.getProcessState(), pjInfoBean.getId());
            }
            // 3. 其他节点，基于原数据更新的逻辑
            else {
                MessageBean<?> NOT_NULL = saveAll(factory, userInfo, jsonNode, pjInfoBean, ctmInfoBean, accountInfoBean, pjMeterList, pmapper);
                if (NOT_NULL != null)
                    return NOT_NULL; // 如果保存失败，返回错误信息
            }

            // 返回主键ID给前端用于刷新单据信息
            if (StringUtils.isNotBlank(pjInfoBean.getId())) {
                Map<String, String> map = new HashMap<>();
                map.put("id", pjInfoBean.getId());
                msg.setData(map);
            }

            // 输出执行结果
            return msg;

        } catch (Exception e) {
            factory.close(false);
            logger.error("工程报装保存失败", e);
            return MessageBean.create(Constant.MESSAGE_INT_FAIL, "工程报装保存失败", null);
        }
    }

    public Integer sendSMS(SessionFactory factory, UserInfoBean userInfo, CtmInfoBean ctmInfoBean) throws Exception {
        Integer flag = 1;
        // 获取模板
        BaseMsgPhrase baseMsgPhrase = factory.getMapper(BaseMsgPhraseMapper.class).select();
        if (baseMsgPhrase == null) {
            return flag;
        }
        String phraseContent = baseMsgPhrase.getPhraseContent().replace("ctmName", ctmInfoBean.getCtmName());
        SendTemMsgAccBean sendBean = new SendTemMsgAccBean();
        sendBean.setNoticeType(1);
        sendBean.setCreateUser(userInfo.getUserInfo().getName());
        sendBean.setMobile(ctmInfoBean.getMobile());
        sendBean.setCreateUser("报装系统通知");
        sendBean.setNoticeContent(phraseContent);
        sendBean.setSystemId(StaticInfo.systemId);
        sendBean.setPlatform(1);
        sendBean.setGroupCode(userInfo.getCurWaterCode());
        @SuppressWarnings("rawtypes")
        com.koron.util.secret.RequestBean reqBean
                = new com.koron.util.secret.RequestBean();
        reqBean.setData(sendBean);
        reqBean.setUrl(StaticInfo.smsSendUrl);
        String result = SecretReqUtil.sendToGatWay(reqBean);
        logger.info("result: " + result);
        // 插入数据库
//			messageInsert(factory, bean, userInfo, result);
        JSONObject jsonObject = JSON.parseObject(result);
        flag = (Integer) jsonObject.get("code");
        return flag;
    }

    /**
     * 保存所有相关信息
     *
     * @param factory         SessionFactory实例，用于数据库操作
     * @param userInfo        用户信息对象
     * @param jsonNode        JSON节点，包含额外数据
     * @param pjInfoBean      项目信息对象
     * @param ctmInfoBean     客户信息对象
     * @param accountInfoBean 账户信息对象
     * @param pjMeterList     项目水表列表
     * @param pmapper         公共管理区域映射器
     * @return 返回消息对象，包含操作结果
     */
    private MessageBean<?> saveAll(SessionFactory factory, UserInfoBean userInfo, JsonNode jsonNode, PjInfoBean pjInfoBean, CtmInfoBean ctmInfoBean, AccountInfoBean accountInfoBean, List<PjMeter> pjMeterList, PubAdminAreaMapper pmapper) {
        String checkResult;
        // 检查节点编号
        String nodeCode = pjInfoBean.getProcessState();
        if (StringUtils.isBlank(nodeCode)) {
            nodeCode = PjInfoService.REGISTER;
        }
        PjInfoQuery pjInfoQuery = new PjInfoQuery();
        boolean approval = pjInfoQuery.isApproval(nodeCode);
        if (approval) {
            return MessageBean.create(Constant.NOT_NULL, nodeCode + " 流程状态不存在。", null);
        }
        // 检查节点字段
        checkResult = checkNode(pjInfoBean, ctmInfoBean, accountInfoBean, nodeCode, factory);
        if (!"OK".equals(checkResult)) {
            return MessageBean.create(Constant.NOT_NULL, checkResult, null);
        }
        // 检查客户、账户修改标记
        if (jsonNode.get("updateCtmFlag") == null) {
            return MessageBean.create(Constant.NOT_NULL, "客户修改标记不能为空。", null);
        }
        if (jsonNode.get("updateAccountFlag") == null) {
            return MessageBean.create(Constant.NOT_NULL, "账户修改标记不能为空。", null);
        }
        String updateCtmFlag = jsonNode.get("updateCtmFlag").asText();
        String updateAccountFlag = jsonNode.get("updateAccountFlag").asText();
        // 判断客户信息是否能修改
        if ("1".equals(updateCtmFlag)) {
            // 保存客户
            saveCtm(factory, userInfo, ctmInfoBean);
        }
        // 判断账户信息是否能修改
        if ("1".equals(updateAccountFlag)) {
            // 保存客户、账户
            saveAccount(factory, userInfo, accountInfoBean, ctmInfoBean.getCtmNo());
        }
        // 编制结算页面的数据状态为审批和结束节点时，流程不允许保存和提交
        if (StringUtils.equals(nodeCode, PjInfoService.PJSETTLEMENT) || StringUtils.equals(nodeCode, PjInfoService.PJPAYMENT)) {
            MessageBean message = verifyPjSettlement(factory, pjInfoBean);
            if (Constant.MESSAGE_INT_SUCCESS != message.getCode()) {
                return message;
            }
        }
        // 保存用水咨询 关键代码！！！
        MessageBean messageBean = savePjConsult(factory, userInfo, pjInfoBean, nodeCode);
        if (messageBean.getCode() == Constant.MESSAGE_INT_FAIL && nodeCode.equals(PjInfoProcessStateEnum.REGISTER_ACCOUNT.getProcessState())) {
            return MessageBean.create(Constant.MESSAGE_INT_FAIL, "工程报装-立户审批通过-数据添加失败", null);
        }
        // 多水表保存
        if (StringUtils.equalsAny(nodeCode, PjInfoService.DESIGN, PjInfoService.DESIGN_APPROVAL, PjInfoService.BUDGET,
                PjInfoService.BUDGET_APPROVAL, PjInfoService.BUILD, PjInfoService.INSTALL_BUILD,
                PjInfoService.CHECK, PjInfoService.METER_HOOK, PjInfoService.DATA_ARCHIVE)) {
            saveMeter(factory, userInfo, pjMeterList, pjInfoBean.getId(), ctmInfoBean, accountInfoBean);
        }
        // 施工完修改满足立户标识
        if (nodeCode.equals(PjInfoService.INSTALL_BUILD)) {
            factory.getMapper(PjInfoMapper.class).updateOpenFlag(pjInfoBean.getId());
        }
        return null;
    }

    /**
     * 保存用水咨询
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public MessageBean<?> savePjConsult(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean, String nodeCode) {
        String consultId = null;
        // 报装登记/资料复核
        if (StringUtils.equalsAny(nodeCode, PjInfoService.REGISTER, PjInfoService.REGISTER_APPROVAL, PjInfoService.INFO_APPROVAL)) {
            consultId = saveRegister(factory, userInfo, pjInfoBean);
        }
        // 勘察邀约节点
        if (StringUtils.equalsAny(nodeCode, PjInfoService.INVITATION_SURVEY)) {
            saveInvitationSurvey(factory, userInfo, pjInfoBean);
        }
        // 勘察节点
        if (StringUtils.equalsAny(nodeCode, PjInfoService.SURVEY)) {
            saveSurvey(factory, userInfo, pjInfoBean);
        }
        // 设计节点
        if (StringUtils.equals(nodeCode, PjInfoService.DESIGN)) {
            saveDesign(factory, userInfo, pjInfoBean);
        }
        // 开票及到账确认节点
        if (StringUtils.equals(nodeCode, PjInfoService.PAYMENT)) {
            savePayment(factory, userInfo, pjInfoBean);
        }
        // 预算/预算审批节点
        if (StringUtils.equalsAny(nodeCode, PjInfoService.BUDGET, PjInfoService.BUDGET_APPROVAL)) {
            saveBudget(factory, userInfo, pjInfoBean);
        }
        // 施工计划
        if (StringUtils.equals(nodeCode, PjInfoService.BUILD)) {
            saveBuild(factory, userInfo, pjInfoBean);
        }
        // 安装施工
        if (StringUtils.equals(nodeCode, PjInfoService.INSTALL_BUILD)) {
            saveInstallBuild(factory, userInfo, pjInfoBean);
        }
        // 立户/立户审批
        if (StringUtils.equalsAny(nodeCode, PjInfoService.REGISTER_ACCOUNT, PjInfoService.REGISTER_ACCOUNT_APPROVAL)) {
            saveRegisterAccount(factory, userInfo, pjInfoBean);
        }
        // 验收邀约审批
        if (StringUtils.equalsAny(nodeCode, PjInfoService.INVITATION_CHECK)) {
            saveCheckInvite(factory, userInfo, pjInfoBean);
        }
        // 验收
        if (StringUtils.equals(nodeCode, PjInfoService.CHECK)) {
            saveCheck(factory, userInfo, pjInfoBean);
        }
        // 工程结算
        if (StringUtils.equals(nodeCode, PjInfoService.PJSETTLEMENT)) {
            savePjSettlement(factory, userInfo, pjInfoBean);
        }
        // 工程收入
        if (StringUtils.equals(nodeCode, PjInfoService.PJPAYMENT)) {
            // savePjSettlementPayment(factory, userInfo, pjInfoBean);
            savePjPayment(factory, userInfo, pjInfoBean);
        }
        // 表记挂接
        if (StringUtils.equals(nodeCode, PjInfoService.METER_HOOK)) {
            saveMeterHook(factory, userInfo, pjInfoBean);
        }
        // 资料归档
        if (StringUtils.equals(nodeCode, PjInfoService.DATA_ARCHIVE)) {
            saveDataArchive(factory, userInfo, pjInfoBean);
        }

        // 竣工资料手续
        if (StringUtils.equals(nodeCode, PjInfoService.CHECK_PROCEDURES)) {
            saveCheckProcedures(factory, userInfo, pjInfoBean);
        }

        return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "", null);
    }

    /**
     * 保存竣工资料手续信息
     */
    private void saveCheckProcedures(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).updateCheckProcedures(pjInfoBean);
    }

    /**
     * 保存开票及到账确认信息
     */
    private void savePayment(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).updatePayment(pjInfoBean);
    }

    /**
     * 保存登记信息
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public String saveRegister(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        factory.getMapper(PjInfoMapper.class).updateRegister(pjInfoBean);
        return pjInfoBean.getId();
    }

    /**
     * 保存勘察邀约
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveInvitationSurvey(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        pjInfoBean.setSurveyInviteStaff(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).updateInvitationSurvey(pjInfoBean);
    }

    /**
     * 保存勘察
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveSurvey(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).updateSurvey(pjInfoBean);
    }

    /**
     * 保存设计
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveDesign(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).updateDesign(pjInfoBean);
    }

    /**
     * 保存预算
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveBudget(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        if (pjInfoBean.getBudgetMoney() == null || pjInfoBean.getBudgetMoney() == 0) {
            pjInfoBean.setBudgetMoney(
                    (pjInfoBean.getBudgetLaborMeterAfter() == null ? 0 : pjInfoBean.getBudgetLaborMeterAfter()) +
                            (pjInfoBean.getBudgetLaborMeterBefore() == null ? 0 : pjInfoBean.getBudgetLaborMeterBefore()) +
                            (pjInfoBean.getBudgetMatrMeterAfter() == null ? 0 : pjInfoBean.getBudgetMatrMeterAfter()) +
                            (pjInfoBean.getBudgetMatrMeterBefore() == null ? 0 : pjInfoBean.getBudgetMatrMeterBefore()) +
                            (pjInfoBean.getBudgetCost() == null ? 0 : pjInfoBean.getBudgetCost()) +
                            (pjInfoBean.getDesignCost() == null ? 0 : pjInfoBean.getDesignCost())
            );
        }
        factory.getMapper(PjInfoMapper.class).updateBudget(pjInfoBean);
    }


    /**
     * 保存施工派单
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveBuild(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        //  pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        // pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        // factory.getMapper(PjInfoMapper.class).saveBuild(pjInfoBean);
    }

    /**
     * 保存安装施工
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveInstallBuild(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setConstEndDate(new Date());
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).saveInstallBuild(pjInfoBean);
    }

    /**
     * 保存立户-工程信息
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    private void saveRegisterAccount(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        factory.getMapper(PjInfoMapper.class).saveRegisterAccount(pjInfoBean);
        // oracleMapper.callCreateFunction(null);
    }

    private void saveCheckInvite(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        factory.getMapper(PjInfoMapper.class).saveCheckInvite(pjInfoBean);
    }

    /**
     * 编制结算修改
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    private void savePjSettlement(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        pjInfoBean.setSetmtDate(new Date());
        factory.getMapper(PjSettlementMapper.class).updateByConsultId(pjInfoBean);
        factory.getMapper(PjInfoMapper.class).savePreSetmt(pjInfoBean);
    }

    /**
     * 工程结算收款修改
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    private void savePjSettlementPayment(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        factory.getMapper(PjInfoMapper.class).savePjSetmtPayment(pjInfoBean);
        PjMeterMapper pjMeterMapper = factory.getMapper(PjMeterMapper.class);
        AccountInfoMapper accountInfoMapper = factory.getMapper(AccountInfoMapper.class);
        // 先统一将水表的余额退款标志置为0
        pjMeterMapper.initBalanceRefundFlag(pjInfoBean.getId());
        if (pjInfoBean.getAccountInfoList() != null) {
            for (AccountInfoBean accountInfo : pjInfoBean.getAccountInfoList()) {
                if (accountInfo.getAccountBalance() <= 0) {
                    throw new RuntimeException("预存余额必须大于等于0");
                }
                // 将水表的余额退款标志置为 1
                pjMeterMapper.updateBalanceRefundFlag(accountInfo.getAccountNo(), 1);
                // 修改账户临时表的余额
                accountInfoMapper.updateAccountBalance(accountInfo.getAccountNo(), accountInfo.getAccountBalance(), AccountInfoBean.ACCOUNTTEMP);
            }
        }
    }

    /**
     * 工程收入
     */
    private void savePjPayment(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        // 判断尾款是否为不为空并大于0
        if (pjInfoBean.getPrepaymentAmountForEnd() == null || pjInfoBean.getPrepaymentAmountForEnd() < 0) {
            pjInfoBean.setPrepaymentAmountForEnd(0.0);
        }
        factory.getMapper(PjInfoMapper.class).savePayment(pjInfoBean);
    }

    /**
     * 保存验收
     *
     * @param factory
     * @param userInfo
     * @param pjInfoBean
     */
    public void saveCheck(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        PjCheckInfoMapper pjCheckInfoMapper = factory.getMapper(PjCheckInfoMapper.class);
        int version = -1;
        List<PjCheckInfoBean> pjCheckInfoBeanList = pjInfoBean.getCheckInfo();
        if (pjCheckInfoBeanList != null && pjCheckInfoBeanList.size() > 0) {
            // 1. 不能删除原有数据
            // pjCheckInfoMapper.del(pjInfoBean.getBillNo());
            for (PjCheckInfoBean pjCheckInfoBean : pjCheckInfoBeanList) {
                // 2. billNo
                pjCheckInfoBean.setBillNo(pjInfoBean.getBillNo());
                // 3. templateId
                pjCheckInfoBean.setTemplateId(pjCheckInfoBean.getId());
                // 4. id
                pjCheckInfoBean.setId(Tools.getObjectId());
                // 5. checkStaff
                pjCheckInfoBean.setCheckStaff(userInfo.getUserInfo().getAcount());
                // 6. version
                if (version == -1) {
                    version = pjCheckInfoMapper.maxVersion(pjCheckInfoBean.getBillNo(), pjCheckInfoBean.getDepartBelong(), pjCheckInfoBean.getCheckStaff());
                }
                pjCheckInfoBean.setVersion(version + 1);
                // 7. checkDate
                if (pjCheckInfoBean.getCheckDate() == null) {
                    pjCheckInfoBean.setCheckDate(new Date());
                }
                pjCheckInfoBean.setCheckDate(pjCheckInfoBean.getCheckDate());
            }
            // 8. 批量新增
            pjCheckInfoMapper.batchInsertPjCheckInfoBean(pjCheckInfoBeanList);
        }
        // 工程报装更新
        pjInfoBean.setUpdateName(userInfo.getUserInfo().getName());
        pjInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
        factory.getMapper(PjInfoMapper.class).saveCheck(pjInfoBean);
    }

    private void saveMeterHook(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        factory.getMapper(PjInfoMapper.class).saveMeterHook(pjInfoBean);
    }

    private void saveDataArchive(SessionFactory factory, UserInfoBean userInfo, PjInfoBean pjInfoBean) {
        pjInfoBean.setUpdateInfo(userInfo);
        factory.getMapper(PjInfoMapper.class).saveDataArchive(pjInfoBean);
    }

    private static String updateCentralizedReadingSystem(String url, UserBean bean, String name) {
        // 获取水表信息
        Map<String, Object> data = new HashMap<String, Object>();
        // 获取表身码
        data.put("code", bean.getMeterNo());
        data.put("group", bean.getTenantId());
        data.put("usn", bean.getUserNo());
        data.put("areaId", bean.getClientContractAddr());
        data.put("installAddr", bean.getSetupMeterAddr());
        data.put("installTime", bean.getSetupMeterDate());
        data.put("position", bean.getSetupMeterLocation());
        data.put("name", name);
        data.put("concentrator", bean.getConcentratorNo());
        com.koron.util.secret.RequestBean reqBean = new com.koron.util.secret.RequestBean();
        reqBean.setUrl(url);
        reqBean.setData(data);
        String result = null;
        try {
            result = SecretReqUtil.sendToJc(reqBean, "updateMeter");

        } catch (Exception e) {
            logger.error("调用集抄系统失败", e);
            return e + "";
        }
        return result;
    }

    /**
     * 保存客户信息
     *
     * @param factory
     * @param userInfo
     * @param ctmInfoBean
     */
    public void saveCtm(SessionFactory factory, UserInfoBean userInfo, CtmInfoBean ctmInfoBean) {
        if (StringUtils.isBlank(ctmInfoBean.getCreditLevel())) {
            ctmInfoBean.setCreditLevel("1");
        }
        if (StringUtils.isBlank(ctmInfoBean.getId())) {
            // 新增
            ctmInfoBean.setId(Tools.getObjectId());
            ctmInfoBean.setCreateName(userInfo.getUserInfo().getName());
            ctmInfoBean.setCreateAccount(userInfo.getUserInfo().getAcount());
            ctmInfoBean.setCtmNo(Tools.getCtmNo(factory, userInfo.getCurWaterCode()));
            factory.getMapper(CtmInfoMapper.class).ctmInfoAdd(ctmInfoBean, 2);
        } else {
            // 修改
            ctmInfoBean.setUpdateName(userInfo.getUserInfo().getName());
            ctmInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
            factory.getMapper(CtmInfoMapper.class).ctmInfoUpdate(ctmInfoBean, 2);
        }
    }

    /**
     * 保存账户信息
     *
     * @param factory
     * @param userInfo
     * @param accountInfoBean
     * @param ctmNo
     */
    public void saveAccount(SessionFactory factory, UserInfoBean userInfo, AccountInfoBean accountInfoBean, String ctmNo) {
        if (StringUtils.isBlank(accountInfoBean.getId())) {
            // 新增
            accountInfoBean.setId(Tools.getObjectId());
            accountInfoBean.setCreateName(userInfo.getUserInfo().getName());
            accountInfoBean.setCreateAccount(userInfo.getUserInfo().getAcount());
            accountInfoBean.setAccountNo(Tools.getAccountNo(factory, userInfo.getCurWaterCode()));
            factory.getMapper(AccountInfoMapper.class).accountInfoAdd(accountInfoBean, 2);
        } else {
            // 修改
            accountInfoBean.setUpdateName(userInfo.getUserInfo().getName());
            accountInfoBean.setUpdateAccount(userInfo.getUserInfo().getAcount());
            factory.getMapper(AccountInfoMapper.class).accountInfoUpdate(accountInfoBean, 2);
        }
    }

    /**
     * 检查登记节点
     *
     * @param pjInfoBean
     * @param ctmInfoBean
     * @param accountInfoBean
     * @return
     */
    public String checkNode(PjInfoBean pjInfoBean, CtmInfoBean ctmInfoBean, AccountInfoBean accountInfoBean, String nodeCode, SessionFactory factory) {
        String checkResult = "";
        // 登记/信息筛查/资料复核节点
        if (StringUtils.equalsAny(nodeCode, PjInfoService.REGISTER, PjInfoService.REGISTER_APPROVAL, PjInfoService.INFO_APPROVAL)) {

            checkResult = checkCtm(ctmInfoBean);
            if (!"OK".equals(checkResult)) {
                return checkResult;
            }
            checkResult = checkRegister(factory, pjInfoBean);
            if (!"OK".equals(checkResult)) {
                return checkResult;
            }
            // 20220111: 兼容账号信息为空的情况
            if (StringUtils.isNotEmpty(accountInfoBean.getAccountType())) {
                checkResult = checkAccount(accountInfoBean);
                if (!"OK".equals(checkResult)) {
                    return checkResult;
                }
            }
        }
        // 勘察邀约节点
        if (StringUtils.equalsAny(nodeCode, PjInfoService.INVITATION_SURVEY)) {
            checkResult = checkInvitationSurvey(pjInfoBean);
            if (!"OK".equals(checkResult)) {
                return checkResult;
            }
        }
        // 勘察节点
        if (StringUtils.equalsAny(nodeCode, PjInfoService.SURVEY)) {
            checkResult = checkSurvey(pjInfoBean);
            if (!"OK".equals(checkResult)) {
                return checkResult;
            }
        }
        // 设计节点
        if (StringUtils.equals(nodeCode, PjInfoService.DESIGN)) {
            checkResult = checkDesign(pjInfoBean);
            if (!"OK".equals(checkResult)) {
                return checkResult;
            }
        }
        // 预算节点
        if (StringUtils.equals(nodeCode, PjInfoService.BUDGET)) {
            checkResult = checkBudget(pjInfoBean);
            if (!"OK".equals(checkResult)) {
                return checkResult;
            }
        }
        // 施工计划
        if (StringUtils.equals(nodeCode, PjInfoService.BUILD)) {
            /*if (pjInfoBean.getConstBeginDate() == null) {
                return "施工开始日期不能为空。";
            }
            if (pjInfoBean.getConstEndDate() == null) {
                return "施工开始日期不能为空。";
            }*/

        }
        // 验收邀约
        if (StringUtils.equals(nodeCode, PjInfoService.INVITATION_CHECK)) {
            if (StringUtils.isBlank(pjInfoBean.getCheckInviteStaff())) {
                return "验收人员不能为空。";
            }
            if (pjInfoBean.getCheckInviteDate() == null) {
                return "验收日期不能为空。";
            }
        }
        return "OK";
    }

    /**
     * 主键字段检查
     *
     * @param pjInfoBean
     * @param ctmInfoBean
     * @param accountInfoBean
     * @return
     */
    public String checkPrimaryKey(PjInfoBean pjInfoBean, CtmInfoBean ctmInfoBean, AccountInfoBean accountInfoBean) {
        if (StringUtils.isBlank(pjInfoBean.getId())) {
            return "主键不能为空。";
        }
        if (StringUtils.isBlank(pjInfoBean.getUserCtmTempId()) || StringUtils.isBlank(ctmInfoBean.getId())) {
            return "客户主键不能为空。";
        }
        if (StringUtils.isBlank(pjInfoBean.getUserAccountTempId()) || StringUtils.isBlank(accountInfoBean.getId())) {
            return "账户主键不能为空。";
        }
        return "OK";
    }

    /**
     * 登记字段检查
     *
     * @param pjInfoBean
     * @return
     */
    public String checkRegister(SessionFactory factory, PjInfoBean pjInfoBean) {
        if (StringUtils.isBlank(pjInfoBean.getPjType())) {
            return "工程类型不能为空。";
        }
        if (StringUtils.isBlank(pjInfoBean.getUrgentFlag() + "")) {
            return "紧急程度不能为空。";
        }
        if (StringUtils.isBlank(pjInfoBean.getBusinessArea())) {
            return "营业区域不能为空。";
        }

        // 20220113: 在工程类型为户表改造的情况下，判断原户号是否为空(key:1,2,3,4,5;value:户表改造...)
        String type = pjInfoBean.getPjType();
        Map<String, String> PPT = Tools.mapDicByCode(factory, "PPT");
        if (PPT.get(type).equals("户表改造")) {
            if (StringUtils.isEmpty(pjInfoBean.getOloUserNo())) {
                return "户表改造时，原户号不能为空！";
            }
        }
        return "OK";
    }

    /**
     * 勘察邀约字段检查
     *
     * @param pjInfoBean
     * @return
     */
    public String checkInvitationSurvey(PjInfoBean pjInfoBean) {
        if (StringUtils.isBlank(pjInfoBean.getSurveyStaff())) {
            return "勘察人员不能为空。";
        }
        return "OK";
    }

    /**
     * 勘察字段检查
     *
     * @param pjInfoBean
     * @return
     */
    public String checkSurvey(PjInfoBean pjInfoBean) {
//        if (StringUtils.isBlank(pjInfoBean.getSurveyStaff())) {
//            return "勘察人员不能为空。";
//        } else
        if (pjInfoBean.getSurveyDate() == null) {
            return "勘察日期不能为空。";
        }
        if (StringUtils.isBlank(pjInfoBean.getSurveyResult())) {
            return "勘察结论不能为空。";
        }
        return "OK";
    }

    /**
     * 设计字段检查
     *
     * @param pjInfoBean
     * @return
     */
    public String checkDesign(PjInfoBean pjInfoBean) {
        if (StringUtils.isBlank(pjInfoBean.getDesignStaff())) {
            return "设计人员不能为空。";
        }
        if (pjInfoBean.getDesignDate() == null) {
            return "设计日期不能为空。";
        }
        return "OK";
    }

    /**
     * 预算字段检查
     *
     * @param pjInfoBean
     * @return
     */
    public String checkBudget(PjInfoBean pjInfoBean) {
        // if (pjInfoBean.getBudgetMoney() == null &&
        //         (((pjInfoBean.getBudgetLaborMeterAfter() == null ? 0 :
        //                                 pjInfoBean.getBudgetLaborMeterAfter()) +
        //                                 (pjInfoBean.getBudgetLaborMeterBefore() == null ? 0 : pjInfoBean.getBudgetLaborMeterBefore()) +
        //                                 (pjInfoBean.getBudgetMatrMeterAfter() == null ? 0 : pjInfoBean.getBudgetMatrMeterAfter()) +
        //                                 (pjInfoBean.getBudgetMatrMeterBefore() == null ? 0 : pjInfoBean.getBudgetMatrMeterBefore()) +
        //                                 (pjInfoBean.getBudgetOther() == null ? 0 : pjInfoBean.getBudgetOther()) +
        //                                 (pjInfoBean.getDesignCost() == null ? 0 : pjInfoBean.getDesignCost())
        //                 ) == 0
        //         )
        // ) {
        //     return "预算合计不能为空。";
        // }
        return "OK";
    }

    /**
     * 客户字段检查
     *
     * @param ctmInfoBean
     * @return
     */
    public String checkCtm(CtmInfoBean ctmInfoBean) {
        if (StringUtils.isBlank(ctmInfoBean.getCtmType())) {
            return "客户类型不能为空。";
        }
        if (StringUtils.isBlank(ctmInfoBean.getCtmName())) {
            return "业主名称不能为空。";
        }
        if (StringUtils.isBlank(ctmInfoBean.getCertType())) {
            return "业主证件类型不能为空。";
        }
        return "OK";
    }

    /**
     * 账户字段检查
     *
     * @param accountInfoBean
     * @return
     */
    public String checkAccount(AccountInfoBean accountInfoBean) {
        if (StringUtils.isBlank(accountInfoBean.getPayWay())) {
            return "缴费方式不能为空。";
        } else if (StringUtils.isBlank(accountInfoBean.getAccountType())) {
            return "账户类型不能为空。";
        }
        return "OK";
    }

    public void saveMeter(SessionFactory factory, UserInfoBean userInfo, List<PjMeter> pjMeterList, String consultId, CtmInfoBean ctmInfoBean, AccountInfoBean accountInfoBean) {
        // 20220323: pjMeterList可能为空
        if (pjMeterList != null && pjMeterList.size() > 0) {
            PjMeterMapper pjMeterMapper = factory.getMapper(PjMeterMapper.class);
            CtmInfoMapper ctmInfoMapper = factory.getMapper(CtmInfoMapper.class);
            AccountInfoMapper accountInfoMapper = factory.getMapper(AccountInfoMapper.class);
            UserMixtureMapper userMixtureMapper = factory.getMapper(UserMixtureMapper.class);
            UserDiscountMapper userDiscountMapper = factory.getMapper(UserDiscountMapper.class);

            for (int i = 0; i < pjMeterList.size(); i++) {
                PjMeter pjMeter = JSON.parseObject(JSON.toJSONString(pjMeterList.get(i)), PjMeter.class);
                String id = pjMeter.getId();
                // 1. 如果是新增
                if (StringUtils.isEmpty(id)) {
                    // 20220128: consultId
                    pjMeter.setConsultId(consultId);
                    // 20220129: userCtmTempId
                    pjMeter.setUserCtmTempId(ctmInfoBean.getId());
                    // 20220130: userAccountTempId
                    pjMeter.setUserAccountTempId(accountInfoBean.getId());
                    // 2. id
                    pjMeter.setId(Tools.getObjectId());
                    // 3. 保存临时用户信息;pjMeter:userInfoTempId;返回userNo
                    String userNo = saveMeterUserInfoTemp(factory, userInfo, pjMeter, ctmInfoBean, accountInfoBean, pjMeter.getMsInfo());
                    // 4. 保存混合用水信息
                    saveMeterUserMixture(userMixtureMapper, userInfo, pjMeter, userNo);
                    // 5. 保存费用折扣
                    saveMeterUserDiscount(userDiscountMapper, userInfo, pjMeter, userNo);
                    // 5. 将工程报装水表信息插入数据库中
                    pjMeterMapper.insert(pjMeter);
                } // 6. 如果是更新
                else {
                    // 7. 保存临时用户信息
                    String userNo = saveMeterUserInfoTemp(factory, userInfo, pjMeter, ctmInfoBean, accountInfoBean, pjMeter.getMsInfo());
                    // 8. 保存混合用水信息
                    saveMeterUserMixture(userMixtureMapper, userInfo, pjMeter, userNo);
                    // 9. 保存费用折扣
                    saveMeterUserDiscount(userDiscountMapper, userInfo, pjMeter, userNo);
                    // 10. 保存临时客户信息
                    ctmInfoMapper.ctmInfoUpdate(ctmInfoBean, CtmInfoBean.CTMTEMP);
                    // 11. 保存临时账户信息
                    accountInfoMapper.accountInfoUpdate(accountInfoBean, AccountInfoBean.ACCOUNTTEMP);
                    // 12. 更新数据
                    pjMeterMapper.update(pjMeter);
                }
            }
        }
    }

    public String saveMeterUserInfoTemp(SessionFactory factory, UserInfoBean userInfo, PjMeter pjMeter, CtmInfoBean ctmInfoBean, AccountInfoBean accountInfoBean, MsInfoDto msInfoDto) {
        UserInfoMapper userInfoMapper = factory.getMapper(UserInfoMapper.class);
        BusinessAreaMapper businessAreaMapper = factory.getMapper(BusinessAreaMapper.class);
        PubAdminAreaMapper pubAdminAreaMapper = factory.getMapper(PubAdminAreaMapper.class);
        PjInfoMapper pjInfoMapper = factory.getMapper(PjInfoMapper.class);
        String dbEnv = DBSourceUtils.getDbEnv(userInfo.getCurWaterCode());
        String on_off = Tools.getConfigValue(dbEnv, "DEFAULT_BOOK_NO_ON_OFF");
        UserBean userBean = pjMeter.getUserInfo();
        String userBeanId = userBean.getId();
        String userNo = userBean.getUserNo();
        // 施工人员账户添加
        if (StringUtils.isNotEmpty(userBean.getMeterBuilder())) {
            OrgUserMapper mapper = factory.getMapper(OrgUserMapper.class);
            OrgUserBean user = mapper.selectByName(userBean.getMeterBuilder());
            if (user != null) {
                userBean.setMeterBuilder(user.getAccount());
            }
        }
        // 用水期限为空兼容
        if (StringUtils.isEmpty(userBean.getUseTimeLimit())) {
            userBean.setUseTimeLimit(null);
        }
        // 换表日期兼容
        if (StringUtils.isEmpty(userBean.getChangeMeterDate())) {
            userBean.setChangeMeterDate(null);
        }
        // 获取工程类型
        String pjType = pjInfoMapper.getPjType(pjMeter.getConsultId());
        Map<String, String> ppt = Tools.mapDicByCode(factory, "PPT");
        // 获取流程节点
        String processState = pjInfoMapper.getProcessState(pjMeter.getConsultId());
        Map<String, String> pcn = Tools.mapDicByCode(factory, "PCN");
        // 1. 如果是新增
        if (StringUtils.isEmpty(userBeanId)) {
            // 1.1 id,tenantId,createAccount,createName,createTime
            userBean.setCreateInfo(userInfo);
            // 1.2 bookNo
            if (on_off.equals("1")) {
                String businessArea = userBean.getBusinessArea();
                // 20220221: 兼容businessArea为空的情况
                if (StringUtils.isNotEmpty(businessArea)) {
                    BusinessAreaBean businessAreaBean = businessAreaMapper.findBusinessAreaInfoById(businessArea);
                    userBean.setBookNo(businessAreaBean.getBookNo());
                }
            }
            // 1.3 clientContractAddr
            if (StringUtils.isNotEmpty(userBean.getClientContractAddrId())) {
                userBean.setClientContractAddr(userBean.getClientContractAddrId());
            }
            // 1.4 setupMeterAddr
            updateSetupMeterAddr(pubAdminAreaMapper, userBean);
            // 1.5 userNo
            if (StringUtils.isBlank(userBean.getUserNo())) {
                userNo = Tools.getUserNo(factory, userInfo.getCurWaterCode());
                userBean.setUserNo(userNo);
            }
            // 1.6 ctmNo,accountNo, status,lockFlag,openDate
            userBean.setCtmNo(ctmInfoBean.getCtmNo());
            userBean.setAccountNo(accountInfoBean.getAccountNo());
            userBean.setStatus("1");
            userBean.setLockFlag(0);
            // 1.8 ctmName,certNo,certType,likeTel,mobile,faxNumber,ctmAddr
            OpenUserAdd openUserAdd = new OpenUserAdd();
            this.ctmInfoToUserInfo(ctmInfoBean, userBean);
            // 1.8 userWaterTypeName
            String useWaterTypeName = openUserAdd.getUseWaterTypeName(userBean.getUseWaterType(), pjMeter.getUserMixtureData(), userInfoMapper);
            userBean.setUseWaterTypeName(useWaterTypeName);
            // 1.9 business_identification
            userBean.setBusinessIdentification(UserInfoTempBusinessIdentification.PJMETER.getState());
            // 1.10 meterNo
            if (msInfoDto != null && StringUtils.isNotEmpty(msInfoDto.getMeterNo())) {
                userBean.setMeterNo(msInfoDto.getMeterNo());
            }
            if (Arrays.asList(PJ_TYPE_NAME).contains(ppt.get(pjType)) && processState == null) {
                // 如果是水表扩缩登记复用原来的水表信息
                UserBean userTemp = userInfoMapper.getUserInfoByUserNo(userBean.getUserNo(), UserBean.USER);
                userTemp.setCreateInfo(userInfo);
                userInfoMapper.userInfoAdd(userTemp, UserBean.USERTEMP);
                userBean.setId(userTemp.getId());

            } else if (Arrays.asList(PJ_TYPE_NAME).contains(ppt.get(pjType)) && processState != null) {
                // 1.11 不是登记节点将数据插入临时表
                userInfoMapper.userInfoAdd(userBean, 2);
            } else {
                // 判断用户编号是否合理
                checkUserNo(factory, userBean, userInfo);
                // 1.11 将数据插入临时表
                userInfoMapper.userInfoAdd(userBean, 2);
            }
            // 1.12 pjMeter:userInfoTempId
            pjMeter.setUserInfoTempId(userBean.getId());
        }
        // 2. 如果是更新
        else {
            // 2.1 修改临时用户信息
            userBean.setUpdateInfo(userInfo);
            // 2.2 meterNo
            if (msInfoDto != null) {
                userBean.setMeterNo(msInfoDto.getMeterNo());
            }
            // 2.3 setupMeterAddr
            updateSetupMeterAddr(pubAdminAreaMapper, userBean);
            if (!Arrays.asList(PJ_TYPE_NAME).contains(ppt.get(pjType))) {
                // 判断用户编号是否合理
                checkUserNo(factory, userBean, userInfo);
            }
            // 2.4 更新临时数据
            userInfoMapper.userInfoUpdate(userBean, 2);
        }

        return userNo;
    }

    /**
     * 用于冗余字段的整理
     *
     * @param ctmBean
     * @param userBean
     */
    public static void ctmInfoToUserInfo(CtmInfoBean ctmBean, UserBean userBean) {
        if (StringUtils.isBlank(userBean.getCtmName())) {
            userBean.setCtmName(ctmBean.getCtmName());
        }
        if (StringUtils.isBlank(userBean.getCertNo())) {
            userBean.setCertNo(ctmBean.getCertNo());
        }
        if (StringUtils.isBlank(userBean.getCertType())) {
            userBean.setCertType(ctmBean.getCertType());
        }
        if (StringUtils.isBlank(userBean.getLinkTel())) {
            userBean.setLinkTel(ctmBean.getLinkTel());
        }
        if (StringUtils.isBlank(userBean.getMobile())) {
            userBean.setMobile(ctmBean.getMobile());
        }
        if (StringUtils.isBlank(userBean.getFaxNumber())) {
            userBean.setFaxNumber(ctmBean.getFaxNumber());
        }
        if (StringUtils.isBlank(userBean.getCtmAddr())) {
            userBean.setCtmAddr(ctmBean.getCtmAddr());
        }

    }

    /**
     * 判断用户编号是否合理
     */
    public static void checkUserNo(SessionFactory factory, UserBean userBean, UserInfoBean userInfo) {
        CodeRuleMapper ruleMapper = factory.getMapper(CodeRuleMapper.class, "_default");
        UserInfoMapper userInfoMapper = factory.getMapper(UserInfoMapper.class);
        TWaterCompanyMapper waterCompanyMapper = factory.getMapper(TWaterCompanyMapper.class, "_default");
        // 判断用户编号是否是数字
        boolean number = NumberUtil.isNumber(userBean.getUserNo());
        if (!number) {
            throw new RuntimeException(userBean.getUserNo() + "-用户编号仅限数字");
        }
        // 获取用户编号的编码规则
        CodeRuleBean userNoRule = ruleMapper.findCodeRuleByCode(USER_NO_RULE_CODE);
        if (userNoRule == null) {
            throw new UserNoException("用户编码规则不存在");
        }
        String first = userNoRule.getRuleExp().substring(0, 1);
        // 获取水司编号
        String curWaterCode = userInfo.getCurWaterCode();
        TWaterCompanyBean newWaterCompany = waterCompanyMapper.selectByCode(curWaterCode);
        if (newWaterCompany == null) {
            throw new UserNoException("水司编号不存在");
        }
        String simplifyNo = newWaterCompany.getSimplifyNo();
        String checkNo = first + simplifyNo;
        String userNo = userBean.getUserNo();
        // 获取用户编号
        GenerateNumber generateNumber = new GenerateNumberImpl();
        String userNo1 = generateNumber.getUserNo(factory, "USER_INFO", userInfo.getCurWaterCode());
        if (userNo.length() != userNo1.length()) {
            throw new UserNoException("用户编号【" + userNo + "】长度错误");
        }
        String userNoPrefix = userNo.substring(0, 4);
        // 不符合规范
        if (!userNoPrefix.equals(checkNo) || !StringUtils.isNumeric(userNo)) {
            throw new UserNoException("用户编号【" + userNo + "】前4位错误");
        }
        // 通过户号查询 用户临时表以及用户正式表的数量 如果大于1 表身用户编号已存在
        int iCount = userInfoMapper.countByUserNoAndId(userBean.getUserNo(), userBean.getId());
        // 用户编号重复
        if (iCount > 0) {
            throw new UserNoException("用户编号【" + userNo + "】已存在");
        }
    }

    public void saveMeterUserMixture(UserMixtureMapper userMixtureMapper, UserInfoBean userInfo, PjMeter pjMeter, String userNo) {
        UserMixtureVO vo = pjMeter.getUserMixtureData();
        if (vo != null && vo.getList() != null) {
            for (UserMixtureBean userMixtureBean : vo.getList()) {
                String id = userMixtureBean.getId();
                if (StringUtils.isEmpty(id)) {
                    userMixtureBean.setCreateInfo(userInfo);
                    userMixtureBean.setTenantId(pjMeter.getId());
                    userMixtureBean.setUserNo(userNo);
                    userMixtureBean.setWaterRatio(userMixtureBean.getWaterRatio().replace("%", ""));
                    userMixtureMapper.insertTemp(userMixtureBean);
                } else {
                    userMixtureBean.setUpdateInfo(userInfo);
                    userMixtureMapper.updateTemp(userMixtureBean);
                }
            }
        }
    }

    public void saveMeterUserDiscount(UserDiscountMapper userDiscountMapper, UserInfoBean userInfo, PjMeter pjMeter, String userNo) {
        UserDiscountVO vo = pjMeter.getDiscountData();
        if (vo != null && vo.getList() != null) {
            for (UserDiscountBean userDiscountBean : vo.getList()) {
                String id = userDiscountBean.getId();
                if (StringUtils.isEmpty(id)) {
                    userDiscountBean.setCreateInfo(userInfo);
                    userDiscountBean.setTenantId(pjMeter.getId());
                    userDiscountBean.setUserNo(userNo);
                    userDiscountMapper.insertTemp(userDiscountBean);
                } else {
                    userDiscountBean.setUpdateInfo(userInfo);
                    userDiscountMapper.updateTemp(userDiscountBean);
                }
            }
        }
    }

    public static void updateSetupMeterAddr(PubAdminAreaMapper pubAdminAreaMapper, UserBean userBean) {
        String clientContractAddr = userBean.getClientContractAddrDetail();
        if (StringUtils.isNotEmpty(clientContractAddr)) {
            userBean.setSetupMeterAddr(userBean.getClientContractAddrDetail());
        }
    }

    // 编制结算页面的数据状态为审批和结束节点时，流程不允许保存和提交
    public static MessageBean verifyPjSettlement(SessionFactory factory, PjInfoBean pjInfo) {
        PjSettlementMapper pjSettlementMapper = factory.getMapper(PjSettlementMapper.class);
        PjSettlementQuery pjSettlementQuery = new PjSettlementQuery();
        pjSettlementQuery.setConsultId(pjInfo.getId());
        List<PjSettlement> pjSettlementList = pjSettlementMapper.getList(pjSettlementQuery);
        for (PjSettlement pjSettlement : pjSettlementList) {
            if (Objects.equals("PROCESSING", pjSettlement.getProcessState()) || Objects.equals("END", pjSettlement.getProcessState())) {
                return MessageBean.create(Constant.MESSAGE_INT_FAIL, "当前流程不允许保存和提交", String.class);
            }
        }
        return MessageBean.create(Constant.MESSAGE_INT_SUCCESS, "", String.class);
    }
}
